﻿using System;
using Autodesk.AutoCAD.ApplicationServices;
using Autodesk.AutoCAD.DatabaseServices;
using Autodesk.AutoCAD.EditorInput;

namespace AutoCADDotNetLibrary
{
    /// <summary>
    /// AOP
    /// </summary>
    public static class SimpleAutoCADAOP
    {
        /// <summary>
        /// AOP基础函数
        /// </summary>
        /// <param name="act">方法</param>
        /// <param name="isUseTransaction">是否使用事务</param>
        /// <param name="isUseCommit">是否使用提交</param>
        /// <param name="isUseLockDocument">是否LockDocument</param>
        /// <param name="isCancellationCommand">是否取消命令</param>
        private static void BaseMethod(Action<Document, Transaction> act, bool isUseTransaction, bool isUseCommit, bool isUseLockDocument, bool isCancellationCommand)
        {
            try
            {
                Document document = Application.DocumentManager.MdiActiveDocument;
                if (document.Database == null)
                    return;

                if (isCancellationCommand)
                {
                    //取消正在执行的命令，但无法继续函数
                    Editor ed = Application.DocumentManager.MdiActiveDocument.Editor;
                    if (!ed.IsQuiescent)
                    {
                        Autodesk.AutoCAD.Internal.Utils.WriteToCommandLine(((char)27) + "");
                        return;
                    }
                }

                DocumentLock doclock = null;
                if (isUseLockDocument)
                    doclock = document.LockDocument();

                using (doclock)
                {
                    if (isUseTransaction)
                    {
                        using (Transaction trans = document.TransactionManager.StartTransaction())
                        {
                            act?.Invoke(document, trans);
                            if (isUseCommit)
                            {
                                trans.Commit();
                            }
                        }
                    }
                    else
                    {
                        act?.Invoke(document, null);
                    }
                }
            }
            catch (Exception ex)
            {
                Application.ShowAlertDialog($"错误信息：{ex.Message}");
            }
        }

        /// <summary>
        /// 运行AutoCAD命令的情况使用
        /// </summary>
        /// <param name="act">方法</param>
        /// <param name="isIdle">命令执行后的空闲时间运行</param>
        public static void RunCommandMethod(Action<Document, Transaction> act, bool isIdle = false)
        {
            if (isIdle)
            {
                ApplicationIdle.IdleMethod(() => BaseMethod((doc, trans) => act?.Invoke(doc, trans), isUseTransaction: true, isUseCommit: false, isUseLockDocument: true, isCancellationCommand: false));
            }
            else
            {
                BaseMethod((doc, trans) => act?.Invoke(doc, trans), isUseTransaction: true, isUseCommit: false, isUseLockDocument: false, isCancellationCommand: false);
            }
        }

        /// <summary>
        /// 特定使用的
        /// </summary>
        /// <param name="act">方法</param>
        /// <param name="isIdle">命令执行后的空闲时间运行</param>
        public static void RunCommandMethodWithoutTransaction(Action<Document> act, bool isIdle = false)
        {
            if (isIdle)
            {
                ApplicationIdle.IdleMethod(() => BaseMethod((doc, trans) => act?.Invoke(doc), isUseTransaction: false, isUseCommit: false, isUseLockDocument: true, isCancellationCommand: false));
            }
            else
            {
                BaseMethod((doc, trans) => act?.Invoke(doc), isUseTransaction: false, isUseCommit: false, isUseLockDocument: false, isCancellationCommand: false);
            }
        }

        /// <summary>
        /// click的调用终点函数调用方式
        /// </summary>
        /// <param name="act">方法</param>
        /// <param name="isUseCommit">是否提交</param>
        public static void RunUIMethod(Action<Document> act, bool isUseCommit)
        {
            BaseMethod((doc, trans) => act?.Invoke(doc), isUseTransaction: true, isUseCommit: isUseCommit, isUseLockDocument: true, isCancellationCommand: true);
        }

        /// <summary>
        /// click的调用终点函数调用方式
        /// </summary>
        /// <typeparam name="T">对应RelayCommand<T></typeparam>
        /// <param name="act">方法</param>
        /// <param name="value">对应RelayCommand<T>传入参数</param>
        /// <param name="isUseCommit">是否提交</param>
        public static void RunUIMethod<T>(Action<Document, T> act, T value, bool isUseCommit)
        {
            BaseMethod((doc, trans) => act?.Invoke(doc, value), isUseTransaction: true, isUseCommit: isUseCommit, isUseLockDocument: true, isCancellationCommand: true);
        }
    }
}
